/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 西安华信智慧数字科技有限公司
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2020/3/1 20:59
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.cloudnote.modules.auth.service;

import com.hyacinth.cloudnote.common.enums.UserStatus;
import com.hyacinth.cloudnote.common.exception.ExceptionHolder;
import com.hyacinth.cloudnote.common.exception.GlobalErrorCode;
import com.hyacinth.cloudnote.common.security.PasswordEncoder;
import com.hyacinth.cloudnote.common.security.UserPrincipal;
import com.hyacinth.cloudnote.modules.auth.converter.UserPrincipalConverter;
import com.hyacinth.cloudnote.modules.common.errorcode.NoteErrorCode;
import com.hyacinth.cloudnote.modules.note.model.User;
import com.hyacinth.cloudnote.modules.note.repository.UserRepository;
import com.hyacinth.cloudnote.modules.note.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * 认证服务
 *
 * @author zhangfb
 * @version 1.0.0.1
 * @since 2020/3/1 20:59
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class AuthService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserPrincipalConverter userPrincipalConverter;

    /**
     * 加载用户信息
     * @param username 手机号、用户名、邮箱
     * @return 用户信息
     */
    public User loadUserByUsername(String username) {
        Optional<User> optional = userRepository.findByUsernameOrMobileOrEmail(username, username, username);
        if (!optional.isPresent()) {
            throw ExceptionHolder.serviceException(GlobalErrorCode.E2000000003);
        }
        User user = optional.get();
        if (!user.isEnabled()) {
            log.error("用户状态异常，username={}，status={}", username, user.getStatus());
            throw ExceptionHolder.serviceException(GlobalErrorCode.E2000000004);
        }
        return user;
    }

    /**
     * 用户登陆
     * @param username 手机号、用户名、邮箱
     * @param password 用户密码
     */
    public UserPrincipal login(String username, String password) {
        User user = loadUserByUsername(username);
        String rawPassword = StringUtils.joinWith("$", password, user.getSalt());
        if (!passwordEncoder.matches(rawPassword ,user.getPassword())) {
            log.error("密码不能匹配，username={}, rawPwd = {}, storePwd={}", username, rawPassword, user.getPassword());
            throw ExceptionHolder.serviceException(GlobalErrorCode.E2000000003);
        }
        return userPrincipalConverter.toUserPrincipal(user);
    }

    /**
     * 注册用户
     * @param username 用户名
     * @param mobile   手机号
     * @param email    邮箱
     * @param password 密码
     * @return 用户
     */
    public User register(String username, String mobile, String email, String password) {
        Optional<User> optional = userRepository.findByUsernameOrMobileOrEmail(username, mobile, email);
        if (optional.isPresent()) {
            log.error("用户已经存在，username={}, mobile = {}, email={}", username, mobile, email);
            throw ExceptionHolder.serviceException(NoteErrorCode.E1000000003,
                    StringUtils.joinWith("&", username, mobile, email));
        }
        // 生成随机盐
        String salt = RandomStringUtils.randomAlphabetic(6);
        String pwd = passwordEncoder.encode(StringUtils.joinWith("$", password, salt));
        User user = new User();
        user.setMobile(mobile);
        user.setUsername(username);
        user.setEmail(email);
        user.setPassword(pwd);
        user.setSalt(salt);
        user.setStatus(UserStatus.ACTIVE);
        return userService.save(user);
    }

}
